﻿#include <occmesh/api/param.h>

#define SIGN(a) ((a) >= 0 ? 1 : -1)
#define ITERATION 10

ParamBuilder::ParamBuilder(const std::vector<gp_Pnt> &cloud) : m_cloud(cloud)
{
}

Handle(Geom_BSplineSurface) ParamBuilder::Build(int Nu, int Nv, int p, int q, std::vector<double> &w, double alpha,
                                                double beta, int times)
{
    auto uv = OCCUtils::ProjectParameterize(m_cloud);

    // 计算误差
    Handle(Geom_BSplineSurface) surf;
    while (times > 0)
    {
        // 最小化弦长拟合曲面
        surf = OCCUtils::Chord(m_cloud, uv, Nu, Nv, p, q, w, alpha, beta);

        TIMER_START(PROJECTION);
        // 更新参数
        for (int i = 0; i < m_cloud.size(); i++)
        {
            double u = uv[i].X();
            double v = uv[i].Y();
            OCCUtils::ProjectWithNearest(surf, m_cloud[i], u, v, 1e-8);
            uv[i] = gp_Pnt2d(u, v);
        }
        TIMER_END(PROJECTION);

        // 增加控制网格规模
        Nu *= 2, Nv *= 2;
        times--;
    }

    return surf;
}
